Open crate files readonly first
authorAlex Crichton <alex@alexcrichton.com>
Sun, 6 Nov 2016 17:06:55 +0000 (09:06 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Sun, 6 Nov 2016 17:07:34 +0000 (09:07 -0800)
This allows Cargo to work with read-only `CARGO_HOME` directories where the
cache was prepared ahead of time.

Closes #3256

src/cargo/sources/registry/remote.rs

index d470618b544ab7c7222e8b6a57407d8e22b69f4d..fd301b0b6f7b2bb68006283ba260df1ca625d087 100644 (file)
@@ -116,6 +116,19 @@ impl<'cfg> RegistryData for RemoteRegistry<'cfg> {
                 -> CargoResult<FileLock> {
         let filename = format!("{}-{}.crate", pkg.name(), pkg.version());
         let path = Path::new(&filename);
+
+        // Attempt to open an read-only copy first to avoid an exclusive write
+        // lock and also work with read-only filesystems. Note that we check the
+        // length of the file like below to handle interrupted downloads.
+        //
+        // If this fails then we fall through to the exclusive path where we may
+        // have to redownload the file.
+        if let Ok(dst) = self.cache_path.open_ro(path, self.config, &filename) {
+            let meta = try!(dst.file().metadata());
+            if meta.len() > 0 {
+                return Ok(dst)
+            }
+        }
         let mut dst = try!(self.cache_path.open_rw(path, self.config, &filename));
         let meta = try!(dst.file().metadata());
         if meta.len() > 0 {